﻿/*   
    Copyright (C) 2009 Galaktika Corporation ZAO

    This file is a part of Galaktika.BusinessMonitor
 
    Galaktika.BusinessMonitor is a free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
      
    You should have received a copy of the GNU General Public License
    along with Galaktika.BusinessMonitor.  If not, see <http://www.gnu.org/licenses/>.
  
    If GPL v.3 is not suitable for your products or company,
    Galaktika Corp provides Galaktika.BusinessMonitor under a flexible commercial license
    designed to meet your specific usage and distribution requirements.
    If you have already obtained a commercial license from Galaktika Corp,
    you can use this file under those license terms.
*/

using System;
using System.Net;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Galaktika.BI.Silverlight.Controls.BallGame
{
    [ScriptableType]
    public class EventArgs<T> : EventArgs
    {
        // Fields
        private T _data;

        // Methods
        public EventArgs(T args)
        {
            this._data = args;
        }

        // Properties
        [ScriptableMember]
        public T Data
        {
            get
            {
                return this._data;
            }
        }
    }

    public class Board
    {
        // Fields
        private BubblesArea bubblesArea;
        private int bubbleSize;
        private Canvas canvas;
        private int height;
        private int nrOfColors;
        private int width;

        // Events
        public event BubblesRemovedEventHandler BubblesRemoved;

        public event GameOverEventHandler GameOver;

        // Methods
        public Board(Canvas canvas, int width, int height, int bubbleSize, int nrOfColors)
        {
            this.canvas = canvas;
            this.width = width;
            this.height = height;
            this.bubbleSize = bubbleSize;
            this.nrOfColors = nrOfColors;
            this.bubblesArea = new BubblesArea(width, height);
            canvas.Width = width * bubbleSize;
            canvas.Height = height * bubbleSize;
            this.FillStartOfGame();
        }

        protected void bubble_BubbleClick(Bubble bubble)
        {
            if (this.BubbleHasNeighbours(bubble))
            {
                int count = 0;
                count = this.Removebubble(bubble.PosX, bubble.PosY, bubble.ColorNr);
                if (count > 0)
                {
                    this.Reorganise();
                    if (this.BubblesRemoved != null)
                    {
                        this.BubblesRemoved(count);
                    }
                }
                if (this.IsGameOver() && (this.GameOver != null))
                {
                    this.GameOver(this);
                }
            }
        }

        protected bool BubbleHasColor(int color, int x, int y)
        {
            Bubble bubble = this.bubblesArea[x, y];
            if (bubble == null)
            {
                return false;
            }
            return (bubble.ColorNr == color);
        }

        protected bool BubbleHasNeighbours(Bubble bubble)
        {
            if (bubble == null)
            {
                return false;
            }
            int posX = bubble.PosX;
            int posY = bubble.PosY;
            int colorNr = bubble.ColorNr;
            return (this.BubbleHasColor(colorNr, posX - 1, posY) || (this.BubbleHasColor(colorNr, posX + 1, posY) || (this.BubbleHasColor(colorNr, posX, posY - 1) || this.BubbleHasColor(colorNr, posX, posY + 1))));
        }

        protected void FillStartOfGame()
        {
            Random random = new Random(((DateTime.Now.Hour * DateTime.Now.Second) * DateTime.Now.Minute) * DateTime.Now.Day);
            for (int i = 0; i < this.width; i++)
            {
                for (int j = 0; j < this.height; j++)
                {
                    Bubble bubble = new Bubble(this.canvas, this.bubbleSize, random.Next(0, this.nrOfColors), i, j);
                    bubble.BubbleClick += new BubbleClickEventHandler(this.bubble_BubbleClick);
                    this.bubblesArea[i, j] = bubble;
                }
            }
        }

        public bool IsBoardClear()
        {
            for (int i = 0; i < this.width; i++)
            {
                for (int j = 0; j < this.height; j++)
                {
                    if (this.bubblesArea[i, j] != null)
                    {
                        return false;
                    }
                }
            }
            return true;
        }

        public bool IsGameOver()
        {
            for (int i = 0; i < this.width; i++)
            {
                for (int j = 0; j < this.height; j++)
                {
                    if (this.BubbleHasNeighbours(this.bubblesArea[i, j]))
                    {
                        return false;
                    }
                }
            }
            return true;
        }

        private void MoveColDown(int x, int y)
        {
            int num = y;
            while (num > 0)
            {
                this.bubblesArea[x, num] = this.bubblesArea[x, num - 1];
                num--;
            }
            this.bubblesArea[x, num] = null;
        }

        private void MoveColLeft(int x)
        {
            int num = x;
            while (num < (this.width - 1))
            {
                for (int j = 0; j < this.height; j++)
                {
                    this.bubblesArea[num, j] = this.bubblesArea[num + 1, j];
                }
                num++;
            }
            for (int i = 0; i < this.height; i++)
            {
                this.bubblesArea[num, i] = null;
            }
        }

        protected int Removebubble(int x, int y, int color)
        {
            int num = 0;
            Bubble bubble = this.bubblesArea[x, y];
            if ((bubble == null) || (bubble.ColorNr != color))
            {
                return num;
            }
            this.bubblesArea[x, y] = null;
            num = 1;
            num += this.Removebubble(x - 1, y, color);
            num += this.Removebubble(x + 1, y, color);
            num += this.Removebubble(x, y - 1, color);
            return (num + this.Removebubble(x, y + 1, color));
        }

        private void Reorganise()
        {
            for (int i = 0; i < this.width; i++)
            {
                int y = 1;
                while (y < this.height)
                {
                    if ((this.bubblesArea[i, y] == null) && (this.bubblesArea[i, y - 1] != null))
                    {
                        this.MoveColDown(i, y);
                    }
                    else
                    {
                        y++;
                    }
                }
            }
            for (int j = this.width - 1; j >= 0; j--)
            {
                if (this.bubblesArea[j, this.height - 1] == null)
                {
                    this.MoveColLeft(j);
                }
            }
        }
    }

 

}
